Шаг 91 - Советы для приложений, устанавливаемых как службы.

По умолчанию система не уведомляет службы о событиях управления питанием. Система осуществляет переходы между различными режимами энергопотребления, не требуя никаких действий со стороны служб.

Если Ваша служба должна участвовать в принятии решений об управлении питанием:

Выполните следующие действия, чтобы получать уведомления о событиях управления питанием:

Служба должна сообщить системе, что она будет принимать и обрабатывать сообщения об управлении питанием следующим образом: При вызове службой функции SetServiceStatus должен устанавливаться бит SERVICE_ACCEPT_POWEREVENT в поле dwControlsAccepted структуры SERVICE_STATUS.

Управляющая функция-обработчик службы должна быть функцией «HandlerEx», как описано в документе по адресу

http://msdn.microsoft.com/library/sdkdoc/winbase/services_3smw.htm

Службы должны использовать функцию RegisterServiceCtrlHandlerEx для регистрации управляющей функции-обработчика «HandlerEx». Управляющие функции-обработчики «HandlerEx» поддерживают новые управляющие коды события управления питанием (в то время как управляющие функции-обработчики типа «Handler» не поддерживают).

После того включения уведомлений о событиях управления питанием Вашей службы она должна будет отвечать на управляющие запросы SERVICE_CONTROL_POWEREVENT и обрабатывать их точно так же, как и сообщения WM_POWERBROADCAST, перечисленные ранее в этой главе и необходимые для соответствия требованиям OnNow/ACPI. Получение сообщения SERVICE_CONTROL_POWEREVENT эквивалентно получению сообщения WM_POWERBROADCAST.

Сравнение уведомлений об управлении питанием
Первая ячейкаВторая ячейка
Не службыСлужбы
Событие управления питанием WM_POWERBROADCASTSERVICE_CONTROL_POWEREVENT
Параметр события wParamdwEventType
Параметр события lParamlpEventData
Если запрос принят Вернуть TRUEВернуть NO_ERROR
Если запрос отклонен Вернуть BROADCAST_QUERY_DENYВернуть любой код ошибки

Пример OnNow:

В приведенном ниже примере показана обработка сообщений об управлении питанием в процедуре wndproc.

//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  НАЗНАЧЕНИЕ:  Обработка сообщений, приходящих главному окну.
//
//  WM_COMMAND	- обработка меню приложения
//  WM_PAINT	- рисование главного окна
//  WM_DESTROY	- отправка сообщения о выходе и возврат
//
//
BOOL g_bAvoidIO = FALSE;
TCHAR g_szTitle[] = _T("Ждущий режим");
TCHAR g_szText[] = _T("Получен запрос о переходе в ждущий режим.  ")
                   _T("Закрыть все файлы и соединения?");

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
   SYSTEM_POWER_STATUS Status;

	switch (message) 
	{
		case WM_COMMAND:
			wmId    = LOWORD(wParam); 
			wmEvent = HIWORD(wParam); 
			// Разбор выбора из меню
			switch (wmId)
			{
				case IDM_ABOUT:
				   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd,
 (DLGPROC)About);
				   break;
				case IDM_EXIT:
				   DestroyWindow(hWnd);
				   break;
				default:
				   return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;

         case WM_POWERBROADCAST:
            switch(wParam)
            {
            case PBT_APMBATTERYLOW:
               // Аккумулятор разряжен.  Используется для определения,
 // нужно ли отменить любой ввод/вывод или можно
 // использовать столько энергии, сколько необходимо.
               g_bAvoidIO = TRUE;
               break;

            case PBT_APMOEMEVENT:
               // Специфические события OEM
               break;

            case PBT_APMPOWERSTATUSCHANGE:
               // Компьютер был помещен или изъят из стационарного устройства, срок работы 
               // аккумулятора менее 5 минут, осталось 10% мощности аккумулятора, энергия
               // аккумулятора изменилась на 3% и т.д. Нас интересует только, подключен ли
               // компьютер к сети.  При питании от аккумулятора необходимо экономно
               // расходовать энергию.

               // Здесь можно производить и другие действия, например, если 
               // выполняется операция, которая продлится дольше, чем 
               // остается времени (мощности) работы аккумулятора,
               // Вы можете остановить процесс и проинформировать пользователя о том, 
               // что времени для завершения текущей операции
               // недостаточно.
               GetSystemPowerStatus(&Status);
               g_bAvoidIO = Status.ACLineStatus == 1 ? FALSE : TRUE;
               break;

            case PBT_APMQUERYSUSPEND:
               // Если потери или повреждения данных не произошло, всегда возвращать
               // TRUE. Если данные могли быть потеряны или повреждены, 
               // проверяйте старший бит значения lParam перед отображением любого 
               // элемента интерфейса пользователя.  
               // Если пользователь не ответит за разумное 
               // время, система перейдет в ждущий режим, так что НЕ ДЕЛАЙТЕ ТАК 
               // без крайней необходимости.
               if (g_bNetDataDirty )
		           {
               	if(lParam & 0x00000001)
			           {
                    if (IDNO == MessageBox(hWnd, g_szText, g_szTitle,
                             MB_YESNO | MB_ICONQUESTION | MB_SYSTEMMODAL))
                     return BROADCAST_QUERY_DENY;
	                 else	
                              // Пользователь требует перехода в спящий режим
                              // с потерей сетевых данных.
		                return TRUE;
	                 }
	              else
	                return BROADCAST_QUERY_DENY;
			        }
               else
                 return TRUE;

            case PBT_APMQUERYSUSPENDFAILED:
               // В обработчике PBT_APMQUERYSUSPEND мы ничего не делаем, так что
               // нет необходимости делать что-либо здесь. Если бы в уведомлении
               // PBT_APMQUERYSUSPEND что-то происходило, здесь 
               // надо было бы отменять эти действия.
               break;

            case PBT_APMRESUMEAUTOMATIC:
               // Это уведомление необходимо обрабатывать, если бы мы обрабатывали 
               // восстановление при поступлении запроса из сети,
               // от модема и т.д. Мы НЕ хотим обрабатывать 
               // эту ситуацию, так же как и событие PBT_APMRESUMESUSPEND
               // потому что в этот момент нет взаимодействия с пользователем.  Как 
               // только система Windows обнаружит вмешательство пользователя 
               // (передвижение мыши, нажатие клавиши и т.д.), система
               // сообщит об этом с помощью уведомления PBT_RESUMESUSPEND.
               break;

            case PBT_APMRESUMECRITICAL:
              // Данное уведомление означает, что система перешла в ждущий режим,
              // не отправив приложениям соответствующие сообщения. Приложение
              // должно восстановить сетевые соединения,
              // повторно открыть все файлы и восстановить общее 
              // состояние приложения. Также необходимо попытаться определить
              // возможную потерю или повреждение данных и уведомить пользователя.
		         break;

            case PBT_APMRESUMESUSPEND:
              // Восстановить все сетевые соединения, сохраненные в функции suspend
              // и/или повторно открыть все файлы и переместить указатели 
              // текущего положения на сохраненные позиции.

              // Если файлы находятся на локальном диске, их состояние будет
              // сохранено; Вам нужно будет отслеживать, какие файлы находятся
              // на локальных дисках, а какие на сетевых 
              // устройствах.

              Resume();
              break;

            case PBT_APMSUSPEND:
               // Сохраните необходимую информацию для восстановления сетевых 
               // соединений и/или закройте все файлы и сохраните информацию, 
               // необходимую для восстановления состояния каждого файла (имя 
               // файла/путь, позиция указателя в файле и т.д.).

               Suspend();
               break;
            }
            break;

		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}
Hosted by uCoz